package cn.edu.cuc.yjsy.admin.views;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.common.util.AbstractEnumerator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.part.ViewPart;

import cn.edu.cuc.yjsy.admin.Activator;
import cn.edu.cuc.yjsy.admin.connection.TargetConnection;
import cn.edu.cuc.yjsy.admin.controllers.StudentController;
import cn.edu.cuc.yjsy.admin.util.MessageHelper;
import cn.edu.cuc.yjsy.admin.util.Op;
import cn.edu.cuc.yjsy.admin.util.StudentAttributes;
import cn.edu.cuc.yjsy.model.ModelPackage;
import cn.edu.cuc.yjsy.model.Student;

public class DetailView extends ViewPart {
	
	public static final String ID = "cn.edu.cuc.yjsy.admin.detailView";
	private Table table;
	private TableEditor tableEditor;
	private Student student;
	private Activator plugin;
	// editing the second column
	private final int EDITABLECOLUMN = 1;
	
	public DetailView() {
		this.plugin = Activator.getDefault();
	}

	public void createPartControl(Composite parent) {
		parent.setLayout(new FillLayout());
		table = new Table(parent, SWT.BORDER | SWT.MULTI | 
				SWT.V_SCROLL | SWT.H_SCROLL | SWT.HIDE_SELECTION);
		table.setHeaderVisible(false);
		table.setLinesVisible(true);
		
		for (int i = 0; i < 2; i++) {
			TableColumn column = new TableColumn(table, SWT.NONE);
			column.setResizable(false);
		}
	    for (int i = 0; i < table.getColumnCount(); i++) {
			table.getColumn(i).pack();
			table.getColumn(i).setWidth(120*(1+i));
		}
		for (int i = 0; i < ModelPackage.STUDENT_FEATURE_COUNT; i++) {
			TableItem item = new TableItem(table, SWT.BORDER);
			item.setText(0, plugin.getResourceString2(StudentAttributes
					.getColumnName(i)));
			item.setFont(0, new Font(Display.getDefault(), "Times New Roman", 9, SWT.BOLD));
			item.setImage(new Image(Display.getDefault(), 1, 17));
		}

		tableEditor = new TableEditor(table);
		//The editor must have the same size as the cell and must
		//not be any smaller than 50 pixels.
		tableEditor.horizontalAlignment = SWT.LEFT;
		tableEditor.grabHorizontal = tableEditor.grabVertical = true;
		tableEditor.minimumWidth = 200;

		table.addMouseListener(new MouseAdapter(){
			public void mouseDoubleClick(MouseEvent e) {
				TableItem item = table.getItem(new Point(e.x, e.y));
	    		int index = table.getTopIndex();
	    		while(index < table.getItemCount()){
	    			item = table.getItem(index);
	    	        Rectangle rect = item.getBounds(EDITABLECOLUMN);
					if (rect.contains(e.x, e.y)) 
						break;
	    			index++;
	    			item = null;
	    		}
	    		if(item == null)
	    			return;
	    		
				CellEditor editor = null;
				// Clean up any previous editor control
				Control oldEditor = tableEditor.getEditor();
				if (oldEditor != null) 
					oldEditor.dispose();

				final EStructuralFeature feature = (EStructuralFeature)item.getData("feature");
				if(feature.isChangeable()){
					final String oldValue = item.getText(EDITABLECOLUMN);
					
					if(feature.getEType() instanceof EEnum){
						EList values = ((EEnum)feature.getEType()).getELiterals();
						String[] value = new String[values.size()];
						int selection = 0;
						for(int i = 0; i < values.size(); i++){
							value[i] = ((EEnumLiteral)values.get(i)).getLiteral();
							if(oldValue.equals(value[i]))
								selection = i;
						}
						editor = new ComboBoxCellEditor(table, value, SWT.BORDER | SWT.READ_ONLY);
						editor.setValue(Integer.valueOf(selection));
					}else{
						editor = new TextCellEditor(table, SWT.BORDER);
						editor.setValue(oldValue);
					}
										
					final CellEditor cellEditor = editor;
					cellEditor.addListener(new ICellEditorListener(){

						public void applyEditorValue() {		
							Object oldObject = null;
							try {
								Object newValue = null;								
								if (feature.getEType() instanceof EEnum) {
									oldObject = ((EEnum) feature.getEType())
									.getEEnumLiteralByLiteral(oldValue).getInstance();
									newValue = ((EEnum) feature.getEType())
										.getEEnumLiteral(((Integer) cellEditor.getValue())
											.intValue()).getInstance();									
								} else if (feature.getEType().getName().equals(
										"EString")){
									oldObject = oldValue;
									newValue = Op.toGBKString((String) cellEditor.getValue());									
								}
								else if (feature.getEType().getName().equals(
										"EDouble")){
									oldObject = Double.valueOf(oldValue);
									newValue = Double.valueOf((String) cellEditor.getValue());									
								}
								if (!oldValue.equals(newValue)) {

									int[] uniqueFeature = {
											ModelPackage.STUDENT__IDNUMBER,
											ModelPackage.STUDENT__NAME,
											ModelPackage.STUDENT__EXAMINENUMBER };
									Map options = new HashMap();
									for (int i = 0; i < uniqueFeature.length; i++) {
										EStructuralFeature feature = ModelPackage.eINSTANCE
												.getStudent()
												.getEStructuralFeature(
														uniqueFeature[i]);
										if (student.eGet(feature) != null) {
											String value = student
													.eGet(feature).toString();
											options.put(Integer
													.valueOf(uniqueFeature[i]),
													Op.toLocaleString(value));
										}
									}

									StudentController controller = new StudentController();
									student.eSet(feature, newValue);
									controller.update(TargetConnection
											.getInstance(), student, options);
									fillTable();
								}
							} catch (Exception e) {
								student.eSet(feature, oldObject);
								MessageBox messageBox = new MessageBox(
										getSite().getShell(), SWT.ICON_ERROR
												| SWT.OK);
								messageBox.setMessage(MessageHelper.VIEW_DETAIL_ERROR_UPDATE);
								messageBox.setText("Error");
								messageBox.open();
							}								
						}

						public void cancelEditor() {
							cellEditor.removeListener(this);
							cellEditor.deactivate();
						}

						public void editorValueChanged(
								boolean oldValidState, boolean newValidState) {
						}
						
					});
					tableEditor.setEditor(cellEditor.getControl(), item, EDITABLECOLUMN);
					cellEditor.setFocus();
				}
			}
		});
	}

	public void setFocus() {
		table.setFocus();
	}
	
	private void fillTable(){
		for (int i = 0; i < ModelPackage.STUDENT_FEATURE_COUNT; i++) {
			TableItem item = table.getItem(i);
			
			EStructuralFeature feature = ModelPackage.eINSTANCE.getStudent()
					.getEStructuralFeature(i);
			String typeName = feature.getEType().getName();
			String value = null;
			if (student.eGet(feature) != null) {
				if (typeName.equals("EString"))
					value = (String) student.eGet(feature);
				else if (feature.getEType() instanceof EEnum)
					value = ((AbstractEnumerator) student.eGet(feature))
							.getLiteral();
				else
					value = student.eGet(feature).toString();

				if (value != null)
					item.setText(1, value);
			}
			item.setFont(1, new Font(Display.getDefault(), "Times New Roman", 9, SWT.NORMAL));
			item.setData("feature", feature);
			if(feature.isChangeable())
				item.setBackground(1, Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
		}
	}
	
	public void setDetail(Student s){
		student = s;
		
		fillTable();
		setPartName(NLS.bind(MessageHelper.VIEW_DETAIL_NAME, s.getName()));
	}
}
